package com.dh.spring.select;

import com.dh.spring.client.bootstrap.GlobalNIOClientBootstrap;
import com.dh.spring.client.file.common.SendEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: YSFY
 * @Date: 2019/12/6 21:28
 * @Pacage_name: com.dh.spring.server.bio
 * @Project_Name: arthas-server
 * @Description: 基于NIO的主选择器
 *
 *  自定义CustomSelector,持有注册在此Selector上的所有通道个数
 *
 */
public class MainClientSelector implements Runnable {
    private final static Logger logger = LoggerFactory.getLogger(MainClientSelector.class);

    @Override
    public void run() {
        //TODO 注册到selector上的所有socket，有任意一个socket读或写事件就绪，则select()方法就会返回，否则阻塞
        while(true) {
            try {
                if (GlobalNIOClientBootstrap.open().select() == 0) { //TODO 返回注册在selector上的就绪socket文件描述符个数
                    TimeUnit.MILLISECONDS.sleep(50);
                    continue;
                }

                //TODO 获取到可选择键，set集合维护了channel与selector的关系，即哪个通道上触发了向Selector注册过的事件通知，循环遍历，这里只遍历的是Selector中发生事件就绪状态变化的通道
                Iterator<SelectionKey> iterators = GlobalNIOClientBootstrap.selector.selectedKeys().iterator();
                while (iterators.hasNext()) {
                    SelectionKey selectionKey = iterators.next();
                    //TODO 移除就绪并被处理的事件
                    iterators.remove();

                    //TODO Selector选择器针对不同通道的发生的就绪状态的事件走不同的通道处理
                    if (selectionKey.isValid() && selectionKey.isAcceptable()) { //TODO 等待接入连接的就绪事件
                        GlobalNIOClientBootstrap.getHandler(((SendEntity) selectionKey.attachment()).getChannelName()).handler(selectionKey);
                    } else if (selectionKey.isValid() && selectionKey.isConnectable()) { //TODO 连接就绪事件
                        GlobalNIOClientBootstrap.getHandler(((SendEntity) selectionKey.attachment()).getHandlerName()).handler(selectionKey);
                    } else if (selectionKey.isValid() && selectionKey.isReadable()) { //TODO 读就绪事件
                        GlobalNIOClientBootstrap.getHandler(((SendEntity) selectionKey.attachment()).getHandlerName()).handler(selectionKey);
                    } else if (selectionKey.isValid() && selectionKey.isWritable()) { //TODO 写就绪事件
                        GlobalNIOClientBootstrap.getHandler(((SendEntity) selectionKey.attachment()).getHandlerName()).handler(selectionKey);
                    }
                }
            } catch (IOException e) {
                logger.error("MainSelector处理Selector通道事件时出现[IOException]异常，堆栈信息：{} ", e);
                continue;
            } catch (InterruptedException e) {
                logger.error("MainSelector处理Selector通道事件时出现[InterruptedException]异常，堆栈信息：{} ", e);
                continue;
            }
        }

    }
}
